#ifndef CLIENTHANDLER_H_
#define CLIENTHANDLER_H_

#include <stdio.h> /* for size_t */

#define MAXFILENAMESIZE 255
#define BLOCKSIZE 512
#define HEADERSIZE 4

//possible opcodes
enum oppCode { readRequest=0x0001, wrightRequest=0x0002, dataRequest=0x0003, ackRequest=0x0004,errRequest=0x0005};

//possible error codes
enum errorCode { notDef=0,fileNotFound=1,accessViolation=2,diskFull=3,illegalTftpOpp=4,unKnownTransferID=5,fileOlreadyExists=6,noSuchUser=7};

/**
 * msg_t
 * 
 * represent a single message between client and server
 */
typedef struct
{
	unsigned int msgID:16;
	unsigned int msgNumber:16;
	char data[512];
	size_t size;
	long offset;
	fpos_t pos;
	unsigned int endTransmission:1;
	unsigned int attempt;
	void* additinalData;
} msg_t, *msg_p;

typedef struct requestStruct_t request_t;
typedef msg_p (*modeFunc_t)(msg_p data);
typedef msg_p (*opCodeFunc_t)(request_t* request, msg_p data);

/**
 * request_t
 * 
 * represent a parsed request that arrived from a client
 */
typedef struct requestStruct_t
{
	char fileName[MAXFILENAMESIZE];
	modeFunc_t modeHandler;
	opCodeFunc_t opcodeHandler;
	opCodeFunc_t acknowledgeHandler;
	struct sockaddr_in *remoteAddr;
	int serverSocket;
	void *addionalData;
} *request_p;

/**
 * author: Assaf Paz.
 * 
 * acceptRequest
 * 
 * request - request string that was received
 * size - size of the request string (request string might contain '\0' within)
 * clientAdder - the client (sender of request) network information struct
 * 
 * log that a request was recieved
 */
void acceptRequest(char* request, int size, struct sockaddr_in* clientAdder);

/**
 * author: Haim Tsolker.
 * 
 * examineRequest
 * 
 * requestStruct - request struct to fill from the request string
 * remoteAddr - the client (sender of request) network information struct
 * request - request string
 * 
 * the request string is parsed and requestStruct is filled accordingly
 * with the following items:
 * fileName - actually the request data, in RRQ situation its the filename
 * modeHandler - a pointer to the mode handler function that deal with translation
 *               for each step of the request.
 * opcodeHandler - a pointer to the opcode handler function that executes a single 
 *                 step of the request.
 * acknowledgeHandler - a pointer to the acknowledge function that check a proper
 *                      acknowledgement from the client on each step.
 * remoteAddr - a pointer to the client (sender of request) network information struct 
 */
request_p examineRequest(request_p requestStruct, struct sockaddr_in *remoteAddr, void *request);

/**
 * author: Assaf Paz.
 * 
 * executeRequest
 * 
 * request - all the required information for handling a request
 * 
 * the function executes request in steps where is step isas follows: 
 * 1) data is extracted using opcodeHanlder function
 * 2) the data get translated by the modeHandler
 * 3) the translated data is sent to the client 
 * 4) wait for a proper acknowledgement (using acknowledgeHandler)
 * 5) if data was acknowledged and this is not the last message
 *    return to 1
 */  
void executeRequest(request_p request);

#endif /*CLIENTHANDLER_H_*/
